package org.snail.attendence.service.impl;

import lombok.extern.log4j.Log4j;
import org.apache.commons.lang3.StringUtils;
import org.snail.attendence.bean.*;
import org.snail.attendence.mapper.AttendenceMapper;
import org.snail.attendence.mapper.AttendenceMongoMapper;
import org.snail.attendence.mapper.WxLeaveMapper;
import org.snail.attendence.service.WxLeaveService;
import org.snail.common.ExcelUtils;
import org.snail.common.FileUtils;
import org.snail.common.dingding.utils.JedisUtils;
import org.snail.constant.AttendenceConstant;
import org.snail.constant.ErrCodeConstant;
import org.snail.constant.WorkSheetConstant;
import org.snail.department.service.impl.DepartmentTreeNodeService;
import org.snail.employee.bean.EmployeesDO;
import org.snail.employee.mapper.EmployeesMapper;
import org.snail.employee.service.impl.EmployeesServiceImpl;
import org.snail.exception.CommonException;
import org.snail.other.mapper.GroupMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;


@Service
@Log4j
public class WxLeaveServiceImpl implements WxLeaveService {

    private static String pathHome = "";
    private static String outfilePath = "";
    @Autowired
    private AttendenceMongoMapper attendenceMongoMapper;
    @Autowired
    private EmployeesServiceImpl employeesService;
    @Autowired
    private AttendenceMapper attendenceMapper;
    @Autowired
    private GroupMapper groupMapper;
    @Autowired
    private AttendanceFileOutputServiceImpl attendanceFileOutputServiceImpl;
    @Autowired
    private WxLeaveMapper wxLeaveMapper;
    @Autowired
    private DepartmentTreeNodeService departmentTreeNodeService;
    @Autowired
    JedisUtils jedisUtils;
    @Autowired
    private AttendanceListServiceImpl attendanceListService;

    List abnormalLeaves = new ArrayList();

    /**
     * 业务逻辑：
     * 1.传入查找出含有Approval的list对象
     * 2.将传入的list对象进行对比，加入forget数组当中
     * 3.向前端展示list页面
     * 4.取出各个钉钉群组，编辑群发消息
     * 5.发送至钉钉群组
     *
     * @return
     */
    public List<AliWorkDTO> findLeaveFromAliWork(AliWorkDTO aliWorkDTO) throws CommonException {
        List<AliWorkDTO> aliWorkHasApprovals = attendenceMapper.findAttendenceByCondition(aliWorkDTO);
//        List<AliWorkDTO> aliWorkHasApprovals = attendenceMongoMapper.findListContainsApproval(MongoCollectionConstant.LAST_ATTENDENCE);
        List<AliWorkDTO> rmList = new ArrayList<>();
        for (AliWorkDTO aliWorkDO : aliWorkHasApprovals) {
            //将含有病假、外出等情况剔除
            if (StringUtils.contains(aliWorkDO.getApproval(), WorkSheetConstant.WX_DAYOFFs) || StringUtils.contains(aliWorkDO.getApproval(), WorkSheetConstant.WX_OUT)
                    || StringUtils.contains(aliWorkDO.getApproval(), WorkSheetConstant.WX_OVERTIME) || StringUtils.contains(aliWorkDO.getApproval(), WorkSheetConstant.WX_OUTWORK) ||
                    StringUtils.isBlank(aliWorkDO.getApproval())) {
                rmList.add(aliWorkDO);
            }
        }
        aliWorkHasApprovals.removeAll(rmList);
        return aliWorkHasApprovals;
    }

    private List<WxLeaveDO> getWxLeave(CommonsMultipartFile file, HttpServletRequest request) {
        pathHome = request.getSession().getServletContext().getRealPath("upload")+"\\wxUpload";
        String outfileName = "out" + file.getOriginalFilename();
        outfilePath = pathHome + "/" + outfileName;
        List listFromExcel = ExcelUtils.getListFromExcel(file, pathHome, WxLeaveDO.class, 1);     //微信与考勤记录相比较，所以导出对象为aliwork
        return listFromExcel;
    }

    /**
     * 微信考勤预览功能
     * 通过工号和日期做查询,和刚导入的数据做对比设置statusNo
     * 0：不变   1：新增  2：修改
     * @param file
     * @param request
     * @return
     * @throws CommonException
     */
    @Override
    public List<WxLeaveDO> previewAttendenceWX(CommonsMultipartFile file, HttpServletRequest request) throws CommonException {
        List<WxLeaveDO> leaveDOS = getWxLeave(file, request);
        compareDBwXAttendance(leaveDOS);
        return leaveDOS;
    }
    /**
     * 和数据库做对比做预览页面
     * 0:不变 1:新增 2:修改
     *
     * @param wxLeaveDOList
     * @throws CommonException
     */
    private void compareDBwXAttendance(List<WxLeaveDO> wxLeaveDOList) throws CommonException {
        for(WxLeaveDO wxLeaveDO:wxLeaveDOList){
            WxleanveCondition wxleanveCondition = new WxleanveCondition();
            wxleanveCondition.setWorkNum(wxLeaveDO.getWorkNum());
            wxleanveCondition.setLeaveDate(wxLeaveDO.getLeaveDate());
            //设置empId
            EmployeesDO emp = employeesService.findEmpByNumOrName(null,wxLeaveDO.getWorkNum(),wxLeaveDO.getEmployeeName());
            if(emp!=null){
                wxLeaveDO.setEmpId(emp.getEmpId());
            }
            List<WxLeaveDO> wxLeaveDOs = wxLeaveMapper.findAttendenceWXByCondition(wxleanveCondition);
            //下面分三种情况
            //1.查询不到此考勤 就说明是新增的数据
            //2.查询到此考勤做对比 相同则不变 不相同则修改
            if(wxLeaveDOs.size()==0){
                wxLeaveDO.setStatusNo(AttendenceConstant.INSERT_NUM);
            }else if(wxLeaveDOs.size()==1){
                //判断是否相同
                WxLeaveDO wxLeaveDB = wxLeaveDOs.get(0);
                if(wxLeaveDB.equals(wxLeaveDO)){
                    wxLeaveDO.setStatusNo(AttendenceConstant.SAME_NUM);
                }else{
                    wxLeaveDO.setStatusNo(AttendenceConstant.UPDATE_NUM);
                }
            }else{
                //查询多条记录
                log.error("通过工号,日期查询微信考勤异常,存在多条记录:"+wxLeaveDO);
            }
        }
    }

    /**
     * 将微信考勤保存至数据库
     * 新增和修改
     * 修改的条件为工号和日期
     * @param wxLeaveDOList
     * @return
     * @throws CommonException
     */
    @Override
    public void saveAttendenceWX(List<WxLeaveDO> wxLeaveDOList) throws CommonException {
        saveWxToDB(wxLeaveDOList);
    }

    private void saveWxToDB(List<WxLeaveDO> leaveDOs) throws CommonException {
        List<WxLeaveDO> saveList = new ArrayList<>();
        List<WxLeaveDO> updateList = new ArrayList<>();
        if(leaveDOs==null){
            log.error("保存微信考勤参数为null");
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM,"参数为空");
        }
        if(leaveDOs.size()==0){
            log.error("保存微信考勤参数为空");
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM,"参数为空");
        }
        for(WxLeaveDO wxLeaveDO:leaveDOs){
            if(StringUtils.isEmpty(wxLeaveDO.getWorkNum())||StringUtils.isEmpty(wxLeaveDO.getLeaveDate())){
                log.error("修改微信考勤数据时需要工号和请假时间:"+wxLeaveDO);
                continue;
            }
            if(wxLeaveDO.getStatusNo()==AttendenceConstant.INSERT_NUM) {
                wxLeaveDO.setCreateTime(new Date());
                saveList.add(wxLeaveDO);
            }else if(wxLeaveDO.getStatusNo()==AttendenceConstant.UPDATE_NUM){
                //在做修改的时候需要有工号和日期这两个参数没有就修改不成功
                wxLeaveDO.setUpdateTime(new Date());
                updateList.add(wxLeaveDO);
            }
        }
        //如果数据量过多可能要分批保存***********
        //新增数据
        if(saveList.size()>0){
            wxLeaveMapper.batchSaveWxLeave(saveList);
        }
        //修改数据
        if(updateList.size()>0){
            wxLeaveMapper.updateWxLeave(updateList);
        }
    }


    /**
     * 获取微信考勤的文件
     * @return
     */
    public List<WxFileDO> findWXFile(HttpServletRequest request){
        List<WxFileDO> fileDOs = new ArrayList<>();
        String p = request.getSession().getServletContext().getRealPath("upload")+"\\wxUpload";
        File[] files = FileUtils.listFiles(p);
        for(File f : files){
            String fileName = f.getName();
            WxFileDO wxFileDO = new WxFileDO();
            wxFileDO.setFileName(fileName);
            //设置上传日期
            //文件的名字 = 上传日期毫秒+"&*.*&"+文件名
            if(!StringUtils.isEmpty(fileName)){
                if(fileName.contains("#0#")){
                    String[] strTemp = fileName.split("#0#");
                    String msTime = strTemp[0];
                    Date d = new Date(Long.parseLong(msTime));
                    wxFileDO.setUpTime(d);
                }
            }else{
                log.error("服务器中的微信考勤文件名称为空");
            }
            fileDOs.add(wxFileDO);
        }
        return fileDOs;
    }

    /**
     * 微信请假明细外包工号和部门需要额外查询
     * 当传入部门为条件的时候需要循环判断每个
     * 微信请假对象中是否在这个部门中
     *
     * @param wxleanveCondition
     * @return
     */
    @Override
    public List<WxLeaveDO> findDetails(WxleanveCondition wxleanveCondition) {
        List<WxLeaveDO> wxLeaveDOs = null;
        try{
            wxLeaveDOs = wxLeaveMapper.findAttendenceWXByCondition(wxleanveCondition);
        }catch (Exception e){
            log.error("查询微信明细失败:"+e);
        }
        findDetailsAliNum(wxLeaveDOs);
        findDetailsDept(wxLeaveDOs);
        //高级查询时过滤部门
        filterDept(wxLeaveDOs,wxleanveCondition);
        return wxLeaveDOs;
    }

    /**
     * 给查询出来的微信请假信息设置外包工号
     * @param wxLeaveDOList
     */
    private void findDetailsAliNum(List<WxLeaveDO> wxLeaveDOList){
        if(wxLeaveDOList!=null){
            for(WxLeaveDO wxLeaveDO : wxLeaveDOList){
                EmployeesDO emp = employeesService.findEmpByNumOrName("", wxLeaveDO.getWorkNum(),wxLeaveDO.getEmployeeName());
                if(emp!=null){
                    wxLeaveDO.setAliNumber(emp.getOutNum());
                    wxLeaveDO.setEmpId(emp.getEmpId());
                }else{
                    log.error("设置外包工号时,微信事假中的人员信息在人员表中查询不到");
                }

            }
        }
    }

    /**
     * 给查询出来的微信请假信息设置部门
     * @param wxLeaveDOList
     */
    private void findDetailsDept(List<WxLeaveDO> wxLeaveDOList){
        if(wxLeaveDOList!=null){
            for(WxLeaveDO wxLeaveDO : wxLeaveDOList) {
                Map<Object, Object> deptEmpMap = departmentTreeNodeService.selectDeptByEmployeeId();
                EmployeesDO emp = employeesService.findEmpByNumOrName("", wxLeaveDO.getWorkNum(), wxLeaveDO.getEmployeeName());
                if (deptEmpMap != null) {
                    if (emp != null) {
                        wxLeaveDO.setDepartment((String) deptEmpMap.get(emp.getEmpId()));
                        wxLeaveDO.setEmpId(emp.getEmpId());
                    } else {
                        log.error("设置部门信息时,微信事假中的人员信息在人员表中查询不到");
                    }
                }
            }
        }
    }

    /**
     * 将高级查询中的部门过滤出来
     * @param wxLeaveDOList
     * @param wxleanveCondition
     */
    private void filterDept(List<WxLeaveDO> wxLeaveDOList,WxleanveCondition wxleanveCondition){
        if(wxLeaveDOList!=null){
            for(int i=0;i<wxLeaveDOList.size();i++){
                WxLeaveDO wxLeaveDO = wxLeaveDOList.get(i);
                String dept = wxleanveCondition.getDepartMent();
                if(!StringUtils.isEmpty(dept)){
                    if(!StringUtils.isEmpty(wxLeaveDO.getDepartment())){
                        if(!wxLeaveDO.getDepartment().contains(dept)){
                            wxLeaveDOList.remove(i);
                        }
                    }
                }
            }
        }

    }

    /**
     * 计算参数对象中的当前月份的 微信请假小时数
     *
     * @param attendanceCheckDO 考勤对象
     */
    public void doEmpWXLeave(AttendanceCheckDO attendanceCheckDO){

    }

    public ResponseEntity<byte[]> wxLeaveDownload(String filePath,HttpServletRequest request) throws IOException, CommonException {
        if(StringUtils.isEmpty(filePath)){
            throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM,"文件名不能为空");
        }
        String pathHome = request.getSession().getServletContext().getRealPath("upload")+"\\wxUpload";
        String outfilePath = pathHome+"/"+filePath;
        return attendanceFileOutputServiceImpl.download(outfilePath);
    }

}
